/*
**  Copyright (c) 2014 Michael Liu(michael.liu.point@gmail.com).
**
**  Project: Gateway Unified Management Platform
**  File:      vlanifopt.c
**  Author:  Michael
**  Date:    06/27/2014
**
**  Purpose:
**    vlan interface method implement.
*/

/* Include files. */

#include "dpmgr.h"
#include "osdep.h"
#include "pfdep.h"
#include "vlanifopt.h"

/* Macro constant definitions. */

/* Type definitions. */

/* Local function declarations. */

static e_ret vlan_if_create(tdp_if * dp_if);
static e_ret vlan_if_destroy(tdp_if * dp_if);
static e_ret vlan_if_enable(tdp_if * dp_if);
static e_ret vlan_if_disable(tdp_if * dp_if);
static e_ret vlan_if_setlinkcfg(tdp_if * dp_if, void *linkcfg, tmask * mask);
static e_ret vlan_if_link(tdp_if * dp_if);
static e_ret vlan_if_unlink(tdp_if * dp_if);
static e_ret vlan_if_collectlinkstat(tdp_if * dp_if);
static e_ret vlan_if_getlinkstat(tdp_if * dp_if, void **linkstat, int *size, tmask * mask);
static e_ret vlan_if_getlinkstatus(tdp_if * dp_if, void **status, int *size, tmask * mask);
static e_ret vlan_if_setnetcfg(tdp_if * dp_if, void *netcfg, tmask * mask);
static e_ret vlan_if_connect(tdp_if * dp_if);
static e_ret vlan_if_disconnect(tdp_if * dp_if);
static e_ret vlan_if_collectnetstat(tdp_if * dp_if);
static e_ret vlan_if_getnetstat(tdp_if * dp_if, void **netstat, int *size, tmask * mask);
static e_ret vlan_if_getnetstatus(tdp_if * dp_if, void **status, int *size, tmask * mask);

/* Macro API definitions. */

/* Global variable declarations. */

e_ret vlan_if_prepare(tdp_if * dp_if)
{

	sysmgr_trace_enter();
	dp_if->create = vlan_if_create;
	dp_if->destroy = vlan_if_destroy;
	dp_if->enable = vlan_if_enable;
	dp_if->disable = vlan_if_disable;
	dp_if->setlinkcfg = vlan_if_setlinkcfg;
	dp_if->getlinkcfg = dpif_getlinkcfg_common;
	dp_if->link = vlan_if_link;
	dp_if->unlink = vlan_if_unlink;
	dp_if->collectlinkstat = vlan_if_collectlinkstat;
	dp_if->getlinkstat = vlan_if_getlinkstat;
	dp_if->getlinkstatus = vlan_if_getlinkstatus;
	dp_if->setnetcfg = vlan_if_setnetcfg;
	dp_if->getnetcfg = dpif_getnetcfg_common;
	dp_if->connect = vlan_if_connect;
	dp_if->disconnect = vlan_if_disconnect;
	dp_if->collectnetstat = vlan_if_collectnetstat;
	dp_if->getnetstat = vlan_if_getnetstat;
	dp_if->getnetstatus = vlan_if_getnetstatus;

	sysmgr_trace_exit();
	return (eRET_SUCCESS);

}

e_ret vlan_if_create(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_destroy(tdp_if * dp_if)
{
	e_ret ret = eRET_SUCCESS;
	tvlan_if_linkcfg *vlan_linkcfg;

	sysmgr_trace_enter();

	vlan_linkcfg = (tvlan_if_linkcfg *) dp_if->linkcfg;
	if ((vlan_linkcfg != NULL) && (vlan_linkcfg->base_if[0] != 0)) {
		os_dep_if_down(dp_if->name);
		ret = os_dep_del_vlan_if(dp_if, vlan_linkcfg->base_if, vlan_linkcfg->vlan_id);
	}

	sysmgr_trace_exit();
	return (ret);
}

e_ret vlan_if_enable(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_disable(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_setlinkcfg(tdp_if * dp_if, void *linkcfg, tmask * mask)
{

	e_ret ret;
	tdata_paths *dp;
	tdp_if *base_if;
	tvlan_if_linkcfg *vlan_linkcfg;
	tvlan_if_linkcfg *new_linkcfg;
	struct list_head *each;

	if (!mask_test_bitmask(mask->mask[0], eVLAN_IF_LINKCFG_MASK0_ALL)) {
		/* No update */
		sysmgr_trace_exit();
		return (eRET_SUCCESS);
	}

	if (dp_if->linkcfg == NULL) {
		vlan_linkcfg = malloc(sizeof(*vlan_linkcfg));
		if (vlan_linkcfg == NULL) {
			sysmgr_err("malloc(%d) failed, err: %d,[%s]\n", sizeof(*vlan_linkcfg), errno, strerror(errno));
			sysmgr_trace_exit();
			return (eRET_NO_RESOURCE);
		}
		memset(vlan_linkcfg, 0, sizeof(*vlan_linkcfg));
		dp_if->linkcfg = vlan_linkcfg;
		dp_if->linkcfg_size = sizeof(*vlan_linkcfg);
	} else {
		vlan_linkcfg = (tvlan_if_linkcfg *) dp_if->linkcfg;
	}

	new_linkcfg = (tvlan_if_linkcfg *) linkcfg;

	if ((mask_test_bit(mask->mask[0], eVLAN_IF_LINKCFG_MASK0_BASEIF)) ||
	    (mask_test_bit(mask->mask[0], eVLAN_IF_LINKCFG_MASK0_VLANID))) {
		dp = dp_if->data_paths;
		/* Look up data path interface entity. */
		base_if = NULL;
		list_for_each(each, &dp->all_ifs) {
			base_if = list_entry(each, tdp_if, all_list);
			if (strcmp(base_if->name, new_linkcfg->base_if) == 0) {
				break;
			} else {
				base_if = NULL;
			}
		}

		if (base_if == NULL) {
			sysmgr_err("No such dp interface[%s].\n", new_linkcfg->base_if);
			mask_clear_bit(mask->mask[0], eVLAN_IF_LINKCFG_MASK0_BASEIF);
			sysmgr_trace_exit();
			return (eRET_NOT_EXIST);
		}
		dp_if->data_if = base_if;

		if (vlan_linkcfg->base_if[0] != 0) {
			os_dep_if_down(dp_if->name);
			os_dep_del_vlan_if(dp_if, vlan_linkcfg->base_if, vlan_linkcfg->vlan_id);
		}

		ret = os_dep_add_vlan_if(dp_if, new_linkcfg->base_if, new_linkcfg->vlan_id);
		if ((ret != eRET_SUCCESS) && (ret != eRET_ALREADY_EXIST)) {
			sysmgr_err("os_dep_add_vlan_if() failed, ret: %d.\n", ret);
			sysmgr_trace_exit();
			return (ret);
		}
		strcpy(vlan_linkcfg->base_if, new_linkcfg->base_if);
		vlan_linkcfg->vlan_id = new_linkcfg->vlan_id;
	}

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_link(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (os_dep_if_up(dp_if->name));
}

e_ret vlan_if_unlink(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (os_dep_if_down(dp_if->name));
}

e_ret vlan_if_collectlinkstat(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_getlinkstat(tdp_if * dp_if, void **linkstat, int *size, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_getlinkstatus(tdp_if * dp_if, void **status, int *size, tmask * mask)
{

	e_ret ret = eRET_SUCCESS;
	teth_if_link_status *link_status;

	sysmgr_trace_enter();

	ret = pf_dep_vlan_if_get_linkstatus(dp_if, &link_status);
	if (ret != eRET_SUCCESS) {
		*size = 0;
		*status = NULL;
	} else {
		if (link_status != NULL) {
			*status = link_status;
			*size = sizeof(*link_status);
		} else {
			*status = NULL;
			*size = 0;
		}
	}

	sysmgr_trace_exit();
	return (ret);
}

e_ret vlan_if_setnetcfg(tdp_if * dp_if, void *netcfg, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_connect(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_disconnect(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_collectnetstat(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_getnetstat(tdp_if * dp_if, void **netstat, int *size, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret vlan_if_getnetstatus(tdp_if * dp_if, void **status, int *size, tmask * mask)
{
	e_ret ret;

	sysmgr_trace_enter();

	ret = dpif_getnetstatus_common(dp_if, (void *)status, size);

	sysmgr_trace_exit();
	return (ret);
}
